

#include "board.h"
#include "main.h"
#include "rtthread.h"
#define DBG_TAG "board"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

#ifdef RT_USING_FINSH
#include <finsh.h>
static void reboot(uint8_t argc, char **argv)
{
	rt_hw_cpu_reset();
}
MSH_CMD_EXPORT(reboot, Reboot System);
#endif /* RT_USING_FINSH */

void SystemClock_Config(void);

extern __IO uint32_t uwTick;
static uint32_t _systick_ms = 1;

/* SysTick configuration */
void rt_hw_systick_init(void)
{
	// Updates the variable SystemCoreClock
	SystemCoreClockUpdate();

	HAL_SYSTICK_Config(SystemCoreClock / RT_TICK_PER_SECOND);

	NVIC_SetPriority(SysTick_IRQn, 15);

	_systick_ms = 1000u / RT_TICK_PER_SECOND;
	if (_systick_ms == 0)
		_systick_ms = 1;
}

/**
 * This is the timer interrupt service routine.
 *
 */
void SysTick_Handler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)
		HAL_IncTick();

	rt_tick_increase();

	/* leave interrupt */
	rt_interrupt_leave();
}

// uint32_t HAL_GetTick(void)
// {
// 	if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)
// 		HAL_IncTick();

// 	return uwTick;
// }

// void HAL_IncTick(void)
// {
// 	uwTick += _systick_ms;
// }

/* re-implement tick interface for STM32 HAL */
// HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
// {
// #ifndef SOC_SERIES_STM32MP1
// 	rt_hw_systick_init();
// #endif

// 	/* Return function status */
// 	return HAL_OK;
// }

/**
 * @brief  This function is executed in case of error occurrence.
 * @param  None
 * @retval None
 */
void _Error_Handler(char *s, int num)
{
	/* USER CODE BEGIN Error_Handler */
	/* User can add his own implementation to report the HAL error return state */
	LOG_E("Error_Handler at file:%s num:%d", s, num);
	while (1)
	{
	}
	/* USER CODE END Error_Handler */
}

/**
 * This function will delay for some us.
 *
 * @param us the delay time of us
 */
void rt_hw_us_delay(rt_uint32_t us)
{
	rt_uint64_t ticks;
	rt_uint32_t told, tnow, tcnt = 0;
	rt_uint32_t reload = SysTick->LOAD;

	ticks = us * (reload / (1000000 / RT_TICK_PER_SECOND));
	told = SysTick->VAL;
	while (1)
	{
		tnow = SysTick->VAL;
		if (tnow != told)
		{
			if (tnow < told)
			{
				tcnt += told - tnow;
			}
			else
			{
				tcnt += reload - tnow + told;
			}
			told = tnow;
			if (tcnt >= ticks)
			{
				break;
			}
		}
	}
}

/**
 * This function will initial STM32 board.
 */
void rt_hw_board_init(void)
{
	HAL_Init();
	SystemClock_Config();
	SystemCoreClockUpdate();
	HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND);
	MX_USART1_UART_Init();

#if defined(RT_USING_HEAP)
	/* Heap initialization */
	rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif

	// #ifdef RT_USING_PIN
	//     rt_hw_pin_init();
	// #endif

	// #ifdef RT_USING_SERIAL
	//     rt_hw_usart_init();
	// #endif

#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
	/* Set the shell console output device */
	rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

#if defined(RT_USING_CONSOLE) && defined(RT_USING_NANO)
	extern void rt_hw_console_init(void);
	rt_hw_console_init();
#endif

#ifdef RT_USING_COMPONENTS_INIT
	/* Board underlying hardware initialization */
	rt_components_board_init();
#endif

	// extern int finsh_system_init();
	// finsh_system_init();
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct = {0};
	RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
	RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
	{
		Error_Handler();
	}
}

#define PRINTF_BUFFER_TAKE
#define PRINTF_BUFFER_RELEASE

int rt_kprintf(const char *fmt, ...)
{
	va_list args;
	rt_size_t length = 0;
	static char rt_log_buf[RT_CONSOLEBUF_SIZE];

	va_start(args, fmt);
	PRINTF_BUFFER_TAKE;

	/* the return value of vsnprintf is the number of bytes that would be
	 * written to buffer had if the size of the buffer been sufficiently
	 * large excluding the terminating null byte. If the output string
	 * would be larger than the rt_log_buf, we have to adjust the output
	 * length. */
	length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
	if (length > RT_CONSOLEBUF_SIZE - 1)
	{
		length = RT_CONSOLEBUF_SIZE - 1;
	}

	// _kputs(rt_log_buf, length);
	for (int i = 0; i < length; i++)
	{
		while ((USART1->SR & 0X40) == 0)
		{
			// 等待发送结束
		}
		USART1->DR = (uint32_t)(rt_log_buf[i]);
	}

	PRINTF_BUFFER_RELEASE;
	va_end(args);

	return length;
}

#ifdef RT_USING_FINSH
#include "usart.h"
int rx_index = 0;
char rt_hw_console_getchar(void)
{
	/* Note: the initial value of ch must < 0 */
	int ch = -1;

	// if (USART1->SR&UART_FLAG_RXNE)
	//{
	//	ch = USART1->DR & 0xff;
	// }
	// else
	//{
	//	rt_thread_mdelay(10);
	// }
	// return ch;
	if (index1 != rx_index)
	{
		ch = rxbuf[rx_index];
		rx_index++;
		if (rx_index >= MAXBUF)
			rx_index = 0;

		// rt_kprintf("rx :%d", index1);
	}
	// rt_kprintf("rx1 :%d", index1);
	rt_thread_mdelay(10);
	return ch;
}
#endif